#include "stdafx.h"
#include <list>
#include <vector>
#include <deque>
#include <map>
#include <hash_map>
#include <set>
#include <bitset>
#include <stack>

#include <string>

void kernel_stlUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS kernel_stlCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS kernel_stlDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);

#ifdef __cplusplus
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath);
#endif

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath)
{
	UNICODE_STRING DeviceName,Win32Device;
	PDEVICE_OBJECT DeviceObject = NULL;
	NTSTATUS status;
	unsigned i;

	RtlInitUnicodeString(&DeviceName,L"\\Device\\kernel_stl0");
	RtlInitUnicodeString(&Win32Device,L"\\DosDevices\\kernel_stl0");

	for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
		DriverObject->MajorFunction[i] = kernel_stlDefaultHandler;

	DriverObject->MajorFunction[IRP_MJ_CREATE] = kernel_stlCreateClose;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = kernel_stlCreateClose;
	
	DriverObject->DriverUnload = kernel_stlUnload;
	status = IoCreateDevice(DriverObject,
							0,
							&DeviceName,
							FILE_DEVICE_UNKNOWN,
							0,
							FALSE,
							&DeviceObject);
	if (!NT_SUCCESS(status))
		return status;
	if (!DeviceObject)
		return STATUS_UNEXPECTED_IO_ERROR;

	DeviceObject->Flags |= DO_DIRECT_IO;
	DeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
	status = IoCreateSymbolicLink(&Win32Device, &DeviceName);

	DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
	
	__asm int 3

	std::string msg("hello kernel stl!i am paged string!\r\n");
	KdPrint((msg.c_str()));

	std::non_paged_string non_paged_msg("hello kernel stl!i am none paged string!\r\n");
	KdPrint((non_paged_msg.c_str()));

	std::list<int, std::non_paged_alloc> sgi_list;
	sgi_list.push_back(100);
	std::vector<int, std::paged_alloc> sgi_vector;
 	sgi_vector.push_back(100);
 	std::stack<int> sgi_stack;
 	sgi_stack.push(111);
	std::deque<int, std::non_paged_alloc> sgi_deque;
 	sgi_deque.push_back(1000);
	std::map<int, int, std::non_paged_alloc> sgi_map;
 	sgi_map[100] = 100;
 	
	std::hash_map<int, int, std::non_paged_alloc> sgi_hash_map;
 
 	std::list<int> list;
 	for (int i = 0; i < 5; i++)
 	{
 		list.push_back(i);
 		sgi_hash_map[i] = i * 100;
 	}
 
 	for (std::hash_map<int, int, std::non_paged_alloc>::const_iterator it = sgi_hash_map.begin(); it != sgi_hash_map.end(); it++)
 	{
 		KdPrint(("first<%d> - second<%d>\r\n", (*it).first, it->second));
 	}
 
 
 	for (std::list<int>::iterator it = list.begin(); it != list.end(); it++)
 	{
 		KdPrint(("%d\r\n", *it));
 	}
 	for (int i = 0; i < list.size(); i++)
 	{
 		std::list<int>::iterator it = std::find(list.begin(), list.end(), i);
 		if (list.end() != it)
 		{
 			KdPrint(("%d\n", *it));
 		}
 	}
 	list.pop_front();
 	for (std::list<int>::iterator it = list.begin(); it != list.end(); it++)
 	{
 		KdPrint(("%d\r\n", *it));
 	}
 	list.pop_back();
 	for (std::list<int>::iterator it = list.begin(); it != list.end(); it++)
 	{
 		KdPrint(("%d\r\n", *it));
 	}
 	list.push_front(100);
 	for (std::list<int>::iterator it = list.begin(); it != list.end(); it++)
 	{
 		KdPrint(("%d\r\n", *it));
 	}
 	list.erase(list.begin());
 	for (std::list<int>::iterator it = list.begin(); it != list.end(); it++)
 	{
 		KdPrint(("%d\r\n", *it));
 	}
 	list.clear();

	return STATUS_SUCCESS;
}

void kernel_stlUnload(IN PDRIVER_OBJECT DriverObject)
{
	UNICODE_STRING Win32Device;
	RtlInitUnicodeString(&Win32Device,L"\\DosDevices\\kernel_stl0");
	IoDeleteSymbolicLink(&Win32Device);
	IoDeleteDevice(DriverObject->DeviceObject);
}

NTSTATUS kernel_stlCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 0;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

NTSTATUS kernel_stlDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
	Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
	Irp->IoStatus.Information = 0;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return Irp->IoStatus.Status;
}
